/*
 * Yabumi, a 2d scrolling shoot-em-up game.
 * Copyright (C) 2003 Gemma Teruaki <terugen@yabumi.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 */

#include <math.h>
#include "../taskmanager.h"
#include "../sprite.h"
#include "../video.h"
#include "../util.h"
#include "item.h"

extern _list_header *active_task_list_header, *expired_task_list_header;
extern _list_header hitcircle_list_header;
_list_header item_list_header;

void Item_Init()
{
  Create_list(&item_list_header);
}

void Item_Free()
{
  Free_list(&item_list_header);
}

_Item *Item_Create(int x, int y, int dx, int dy, _item_type item_type)
{
  _list_item *list_item;
  list_item = (_list_item *)pmalloc(sizeof(_list_item));
  Add_item_last(&item_list_header, list_item);
  _Item *item = &list_item->data.Item;
  item->root = list_item;

  item->x = x;
  item->y = y;
  item->dx = dx;
  item->dy = dy;
  item->item_type = item_type;
  return item;
}

task Item_Add(_option *optv)
{
  _Item *item;
  item = (_Item *)optv->socket[0];
  Task_Add(Item_Draw, item, NULL, INFINITY_COUNT);
  Task_Add(Item_Move, item, NULL, INFINITY_COUNT);
}

task Item_Move(_option *optv)
{
  _Item *item;
  item = (_Item *)optv->socket[0];

  if (optv->count <= -1 * ITEM_LIFETIME ) {
    optv->count = KILL_COUNT;
    Task_Add(Item_Kill, item, NULL, ONETIME_COUNT);
    return;
  };

  item->x += item->dx >> 8;
  item->y += item->dy >> 8;
  /* status check start */
  _list_item *list_item = hitcircle_list_header.next->next;
  _Hitcircle *hitcircle;

  if (optv->count < INFINITY_COUNT - 3) {
    while (list_item != hitcircle_list_header.prev) {
      hitcircle = &list_item->data.Hitcircle;
      if (distance(item->x, item->y, hitcircle->x, hitcircle->y) <= 
	  hitcircle->radius + ITEM_COLLISION_DISTANCE) {
	/*HIT!*/
	switch (item->item_type) {
	case __item_missile:
	  hitcircle->was_hit = __hit_item_missile;
	  break;
	case __item_flame:
	  hitcircle->was_hit = __hit_item_flame;
	  break;
	};
	optv->count = KILL_COUNT;
	Task_Add(Item_Kill, item, NULL, ONETIME_COUNT);
	return;
	break;
      };
      list_item = list_item->next;
    };
  };
  /* status check end */
};

task Item_Draw(_option *optv)
{
  _Item *item;
  item = (_Item *)optv->socket[0];

  int i;
  SDL_Surface *image;
  i = (optv->count / -4) % 3;
  image = Sprite_Item[i];
  Sprite_Add(item->x, item->y, Z_ORDER_D2, image);
}

task Item_Kill(_option *optv)
{
  _Item *item;
  item = (_Item *)optv->socket[0];

  int i;
  _list_item *list_item;
  _task_item *task_item;

  if (optv->count == ONETIME_COUNT) {
    list_item = active_task_list_header->next->next;
    while (list_item != active_task_list_header->prev) {
      task_item = &list_item->data.task_item;
      for (i = 0; i < MAX_SOCKET; i++) {
	if (task_item->option.socket[i] == item) {
	  task_item->option.count = KILL_COUNT;
	};
      };
      list_item = list_item->next;
    };
    list_item = expired_task_list_header->next->next;
    while (list_item != expired_task_list_header->prev) {
      task_item = &list_item->data.task_item;
      for (i = 0; i < MAX_SOCKET; i++) {
	if (task_item->option.socket[i] == item) {
	  task_item->option.count = KILL_COUNT;
	};
      };
      list_item = list_item->next;
    };
    Kill_item(&item_list_header, (_list_item *)item->root);
    pfree(item->root);
  };
}
